﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Services.Client;
using System.Linq;

using Caliburn.Micro;

using Microsoft.Practices.Unity;

using TheKitchen.Client.Commanding;
using TheKitchen.Client.Querying;
using TheKitchen.Client.Services;

namespace TheKitchen.Client.ViewModels
{
    public class SearchViewModel : PropertyChangedBase, IActivate
    {
        #region Private Definition

        private string partialName;

        private string partialDescription;

        private double minimumRating;
        private IEnumerable<Recipe> recipes = new Recipe[0];
        private const int MaxRating = 5;

        #endregion

        public event EventHandler<ActivationEventArgs> Activated;

        [Dependency]
        public ICommandAgent CommandAgent { get; set; }

        [Dependency]
        public IWindowManager WindowManager { get; set; }

        [Dependency]
        public IQueryAgent QueryAgent { get; set; }

        public string PartialName
        {
            get { return partialName; }
            set
            {
                partialName = value;
                NotifyOfPropertyChange(() => PartialName);
            }
        }

        public string PartialDescription
        {
            get { return partialDescription; }
            set
            {
                partialDescription = value;
                NotifyOfPropertyChange(() => PartialDescription);
            }
        }

        public double MinimumRating
        {
            get { return minimumRating; }
            set
            {
                minimumRating = value;
                NotifyOfPropertyChange(() => MinimumRating);
            }
        }

        public IEnumerable<Recipe> Recipes
        {
            get { return recipes; }
            set
            {
                UntrackRecipeChanges();

                recipes = value;
                NotifyOfPropertyChange(() => Recipes);
                TrackRecipeChanges();
            }
        }

        private void TrackRecipeChanges()
        {
            foreach (var recipe in recipes)
            {
                recipe.PropertyChanged += OnRecipePropertyChanged;
            }
        }

        private void UntrackRecipeChanges()
        {
            foreach (var recipe in recipes)
            {
                recipe.PropertyChanged -= OnRecipePropertyChanged;
            }
        }

        private void OnRecipePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var recipe = (Recipe)sender;

            if (e.PropertyName == "Rating")
            {
                CommandAgent.Send(new RateRecipeCommand
                {
                    Id = recipe.Id,
                    Version = recipe.Version,
                    Rating = recipe.Rating.Value
                });
            }
        }

        public bool IsActive
        {
            get { return true; }
        }

        public void Activate()
        {
            MinimumRating = 0;
            PartialDescription = "";
            PartialName = "";

            CommandAgent.CommandsSent += OnCommandsSent;
        }

        private void OnCommandsSent(object sender, CommandsSentEventArgs e)
        {
            if (e.Commands.Any(c => c is AddNewRecipeCommand))
            {
                // If a new recipe was added, force reloading the recipes from the server.
                FindRecipes();
            }
        }

        public void FindRecipes()
        {
            QueryAgent.FindRecipes(
                (int?) (minimumRating * MaxRating), partialName, partialDescription, 
                results => Recipes = results);
        }

        public void AddNewRecipe()
        {
            var newRecipeViewModel = IoC.GetInstance(typeof(NewRecipeViewModel), null);
            WindowManager.ShowDialog(newRecipeViewModel);
        }
    }
}